home *** CD-ROM | disk | FTP | other *** search
/ Visual Cafe 3 / Visual Cafe 3.ISO / Vcafe / Source.bin / ButtonBase.java < prev    next >
Text File  |  1998-10-20  |  52KB  |  1,637 lines

  1. package symantec.itools.awt;
  2.  
  3. import java.awt.*;
  4. import java.applet.*;
  5. import java.awt.event.KeyEvent;
  6. import java.awt.event.FocusEvent;
  7. import java.awt.event.MouseEvent;
  8. import java.awt.event.ActionEvent;
  9. import java.awt.event.ActionListener;
  10. import java.net.URL;
  11. import java.beans.PropertyVetoException;
  12. import java.beans.PropertyChangeListener;
  13. import java.beans.VetoableChangeListener;
  14. import java.beans.PropertyChangeEvent;
  15. import java.lang.IllegalArgumentException;
  16. import symantec.itools.awt.util.ColorUtils;
  17. import symantec.itools.util.Timer;
  18. import symantec.itools.util.GeneralUtils;
  19. import java.util.ResourceBundle;
  20.  
  21. //    05/30/97    LAB    Updated to support Java 1.1
  22. //    06/24/97    LAB    Made the button behave like a button. i.e. When you press the
  23. //                    button, then move off of it, it responds.  This also affects the
  24. //                    notification process.
  25. //                    Fixed problem which required setNotifyDelay() to be
  26. //                    called before setNotifyWhilePressed().
  27. //    06/26/97    LAB    Changed the way the button is drawn.  Now it uses an offscreen
  28. //                    Image as its drawing buffer via updateButtonImage().  Added
  29. //                    capabilities to allow the button to have a user definable color,
  30. //                    and the highlights are derived from that.  Also added a user
  31. //                    definable border color.
  32. //    06/27/97    LAB    Added UseOffset property to allow the button to draw differently
  33. //                    if the user wants objects in the button (like a direction arrow, or
  34. //                    image) to be offset vertically and horizontally by the bevel height
  35. //                    when the button is drawn is its down state.  Changed the default bevel
  36. //                    height to 2 pixels.
  37. //    07/09/97    LAB    Added LinkURL property and supporting properties/methods/members
  38. //                    to allow buttons to have a URL associated with them by defualt.
  39. //                    Added ShowURLStatus property to allow control over the status
  40. //                    messaging for the linkURL.  Condensed all of the java.awt.whatever
  41. //                    imports to java.awt.* for readability. Added minimumSize() and
  42. //                    preferedSize() methods. Updated the enable() and disable() methods
  43. //                    to the new setEnabled() method.
  44. //    07/13/97    RKM    Fixed misspelling of prefered
  45. //    07/19/97    LAB    Added deprecated preferredSize and minimumSize to call the non-deprecated versions.
  46. //  07/23/97    CAR marked fields transient as needed, inner classes implement java.io.Serializable
  47. //    08/05/97    LAB    Added a call to clipRect in the updateButtonImage method to clip subsequent
  48. //                    drawings to the internal button area (sans border and bevel).
  49. //    08/06/97    LAB    Added buttonImageGraphics as a protected data member for use in child
  50. //                    classes overridden updateButtonImage calls.  This allows the cliping
  51. //                    that is done in the ButtonBase to propagate correctly.
  52. //                    Removed all traces of infoTips.
  53. //  08/23/97    CAR button can now be tabbed to and from
  54. //                  when button has focus on Windows a broken line outline will indicate focus
  55. //  08/25/97    CAR when property showFocus is set to true a broken line outline will indicate focus
  56. //                  on Windows showFocus defaults to true, on all other platforms it defaults to false
  57. //  08/28/97    CAR when showFocus is true and button has focus and not on the Macintosh platform, pressing
  58. //                  the space bar will press the button
  59. //  09/01/97    CAR setAppletContext now also called from addNotify in addition to being called from
  60. //                  validate (validate not called when applet loaded in IE)
  61. //    09/11/97    LAB    Moved code to display URL Link outside check to see if button is pressed
  62. //                    (Addresses Mac Bug #7606).
  63. //    10/05/97    LAB    Changed names of strings in PropertyChangeEvent handling to follow Bean Spec
  64. //                    naming conventions.  Added mechanism for internally constrained properties
  65. //                    to be validated after the component is added to the form to avoid code-gen
  66. //                    order specific dependencies.
  67. //    10/06/97    LAB    Changed addNotify to call it's super after listeners are hooked up so
  68. //                    verifyContstrainedPropertyValues will be called after the listeners
  69. //                    are hooked up.  Added simulateClick method.  Changed setBevelHeight
  70. //                    to set the temp value to the current value when changing the current
  71. //                    value.  Changed getBevelHeight to return the temp value if the
  72. //                    component is not added. This fixes a problem at design time where the
  73. //                    component would revert to it's default state after a back run.
  74. //    09/23/98    LAB    Added work arround for potential problem on Unix where paint gets called with
  75. //                    zero width and height (Addresses bug 61447 and 62425).
  76. //                  Removed setting of context to null in setLinkURL() (why was it there?).
  77. //                  (Addresses bug 56084)
  78.  
  79. /**
  80.  * An abstract class used to implement special Symantec buttons.
  81.  * It supports 3-D beveled borders, and the posting of continuous
  82.  * notification events while the button is pressed.
  83.  * <p>
  84.  * @version 1.1, June 26, 1997
  85.  * @author Symantec
  86.  */
  87. public abstract class ButtonBase extends Canvas
  88. {
  89.     /**
  90.      * Constructs a default ButtonBase. The defaults are no notifyWhilePressed,
  91.      * no offset, and a bevel height of 2.
  92.      */
  93.     protected ButtonBase()
  94.     {
  95.         pressed                = false;
  96.         released            = true;
  97.         notifyWhilePressed    = false;
  98.         running                = false;
  99.         notified            = false;
  100.         useOffset            = false;
  101.         showURLStatus        = true;
  102.         isAdded                = false;
  103.         notifyTimer            = null;
  104.         notifyDelay            = 1000;
  105.         bevel                = 2;
  106.         pressedAdjustment    = 0;
  107.         tempBevelHeight        = bevel;
  108.  
  109.         try
  110.         {
  111.             setBorderColor(Color.black);
  112.             setButtonColor(SystemColor.control);
  113.         }
  114.         catch (PropertyVetoException exc) {}
  115.  
  116.         if(symantec.itools.lang.OS.isWindows())
  117.         {
  118.             try {
  119.                 setShowFocus(true);
  120.             } catch (PropertyVetoException e) { }
  121.         }
  122.     }
  123.  
  124.     /**
  125.      * Sets the "height" (cross-section) of a beveled edge, in pixels.
  126.      * @param height the size of the bevel in pixels
  127.      * @exception PropertyVetoException
  128.      * if the specified property value is unacceptable
  129.      * @see #getBevelHeight
  130.      */
  131.     public void setBevelHeight(int height) throws PropertyVetoException
  132.     {
  133.         if(isAdded)
  134.         {
  135.             if(bevel != height)
  136.             {
  137.                 Integer oldValue = new Integer(bevel);
  138.                 Integer newValue = new Integer(height);
  139.  
  140.                 vetos.fireVetoableChange("bevelHeight", oldValue, newValue);
  141.  
  142.                 bevel = height;
  143.                 tempBevelHeight = height;
  144.  
  145.                 repaint();
  146.  
  147.                 changes.firePropertyChange("bevelHeight", oldValue, newValue);
  148.             }
  149.         }
  150.         //We store the value until we are added then set the value to avoid code-gen order dependencies.
  151.         else
  152.         {
  153.             tempBevelHeight = height;
  154.         }
  155.     }
  156.  
  157.     /**
  158.      * Returns the current "height" (cross-section) of a beveled edge, in pixels.
  159.      * @return the current bevel height in pixels.
  160.      * @see #setBevelHeight
  161.      */
  162.     public int getBevelHeight()
  163.     {
  164.         return isAdded ? bevel : tempBevelHeight;
  165.     }
  166.  
  167.     /**
  168.      * Sets whether the button will continually post notify events while pressed.
  169.      * @param flag true to post notify events; false to not post events
  170.      * @exception PropertyVetoException
  171.      * if the specified property value is unacceptable
  172.      * @see #isNotifyWhilePressed
  173.      * @see #setNotifyDelay
  174.      * @see #getNotifyDelay
  175.      */
  176.     public void setNotifyWhilePressed(boolean flag) throws PropertyVetoException
  177.     {
  178.         if(notifyWhilePressed != flag)
  179.         {
  180.             Boolean oldValue = new Boolean(notifyWhilePressed);
  181.             Boolean newValue = new Boolean(flag);
  182.  
  183.             vetos.fireVetoableChange("notifyWhilePressed", oldValue, newValue);
  184.  
  185.             notifyWhilePressed = flag;
  186.  
  187.             if (notifyWhilePressed)
  188.             {
  189.                 notifyTimer = new Timer(notifyDelay, true);
  190.                 notifyTimer.addActionListener(action);
  191.             }
  192.             else if (notifyTimer != null)
  193.             {
  194.                 notifyTimer = null;
  195.             }
  196.  
  197.             changes.firePropertyChange("notifyWhilePressed", oldValue, newValue);
  198.         }
  199.     }
  200.  
  201.     /**
  202.      * Gets whether the button will continuously post events while pressed.
  203.      * @return true if it will continuously post events while pressed, false
  204.      * otherwise
  205.      * @see #setNotifyWhilePressed
  206.      * @see #setNotifyDelay
  207.      * @see #getNotifyDelay
  208.      */
  209.     public boolean isNotifyWhilePressed()
  210.     {
  211.         return notifyWhilePressed;
  212.     }
  213.  
  214.     /**
  215.      * @deprecated
  216.      * @see #isNotifyWhilePressed
  217.      */
  218.     public boolean getNotifyWhilePressed()
  219.     {
  220.         return isNotifyWhilePressed();
  221.     }
  222.  
  223.     /**
  224.      * Sets the notification event delay in milliseconds.
  225.      * @param delay the delay between notification events in milliseconds
  226.      * @exception PropertyVetoException
  227.      * if the specified property value is unacceptable
  228.      * @see #setNotifyWhilePressed
  229.      * @see #getNotifyDelay
  230.      */
  231.     public void setNotifyDelay(int delay) throws PropertyVetoException
  232.     {
  233.         if(notifyDelay != delay)
  234.         {
  235.             Integer oldValue = new Integer(notifyDelay);
  236.             Integer newValue = new Integer(delay);
  237.  
  238.             vetos.fireVetoableChange("notifyDelay", oldValue, newValue);
  239.             notifyDelay = delay;
  240.             if(notifyTimer != null)
  241.                 notifyTimer.setDelay(notifyDelay);
  242.             changes.firePropertyChange("notifyDelay", oldValue, newValue);
  243.         }
  244.     }
  245.  
  246.     /**
  247.      * Returns the current delay in milliseconds between notification events.
  248.      * @see #setNotifyWhilePressed
  249.      * @see #setNotifyDelay
  250.      */
  251.     public int getNotifyDelay()
  252.     {
  253.         return notifyDelay;
  254.     }
  255.  
  256.     /**
  257.      * Sets whether objects in the button will be offset down and to the right
  258.      * by the bevel height amount or not.
  259.      * This also impacts the way the button is drawn when it is pressed.
  260.      * @param flag true to have objects use the offset; false to have objects not move.
  261.      * @exception PropertyVetoException
  262.      * if the specified property value is unacceptable
  263.      * @see #isUseOffset
  264.      * @see #setBevelHeight
  265.      * @see #getBevelHeight
  266.      */
  267.     public void setUseOffset(boolean flag) throws PropertyVetoException
  268.     {
  269.         if(useOffset != flag)
  270.         {
  271.             Boolean oldValue = new Boolean(useOffset);
  272.             Boolean newValue = new Boolean(flag);
  273.             vetos.fireVetoableChange("useOffset", oldValue, newValue);
  274.  
  275.             useOffset = flag;
  276.             repaint();
  277.  
  278.             changes.firePropertyChange("useOffset", oldValue, newValue);
  279.         }
  280.     }
  281.  
  282.     /**
  283.      * Gets whether objects in the button will be offset down and to the right
  284.      * by the bevel height amount or not.
  285.      * This also impacts the way the button is drawn when it is pressed.
  286.      * @return <code>true</code> if bevel offset is used
  287.      * @see #setUseOffset
  288.      */
  289.     public boolean isUseOffset()
  290.     {
  291.         return useOffset;
  292.     }
  293.  
  294.     /**
  295.      * Sets whether this component will visually indicate when it has the focus.
  296.      * This is done by drawing a focus rectangle within the component as needed.
  297.      * @param flag <code>true</code> to visually indicate focus,
  298.      * <code>false</code> to never indicate focus
  299.      * @exception PropertyVetoException
  300.      * if the specified property value is unacceptable
  301.      * @see #isShowFocus
  302.      */
  303.     public void setShowFocus(boolean flag) throws PropertyVetoException
  304.     {
  305.         if(showFocus != flag)
  306.         {
  307.             Boolean oldValue = new Boolean(showFocus);
  308.             Boolean newValue = new Boolean(flag);
  309.             vetos.fireVetoableChange("showFocus", oldValue, newValue);
  310.  
  311.             showFocus = flag;
  312.  
  313.             changes.firePropertyChange("showFocus", oldValue, newValue);
  314.         }
  315.     }
  316.  
  317.     /**
  318.      * Gets whether this component will visually indicate when it has the focus.
  319.      * This is done by drawing a focus rectangle within the component as needed.
  320.      * @return <code>true</code> if the focus is visually indicated,
  321.      * <code>false</code> if the focus is never indicated
  322.      * @see #setShowFocus
  323.      */
  324.     public boolean isShowFocus()
  325.     {
  326.         return showFocus;
  327.     }
  328.  
  329.     /**
  330.      * @deprecated
  331.      * @see #isShowFocus
  332.      */
  333.     public boolean getShowFocus()
  334.     {
  335.         return isShowFocus();
  336.     }
  337.  
  338.     /**
  339.      * Sets whether the linkURL will be displayed in the status area when the mouse
  340.      * is over the button.
  341.      * This flag also controls erasing of the status area after the URL has been displayed.
  342.      * @param flag true if the linkURL will be displayed in the status area when the mouse
  343.      * is over the button; false if not.
  344.      * @exception PropertyVetoException
  345.      * if the specified property value is unacceptable
  346.      * @see #isShowURLStatus
  347.      */
  348.     public void setShowURLStatus(boolean flag) throws PropertyVetoException
  349.     {
  350.         if(showURLStatus != flag)
  351.         {
  352.             Boolean oldValue = new Boolean(showURLStatus);
  353.             Boolean newValue = new Boolean(flag);
  354.             vetos.fireVetoableChange("showURLStatus", oldValue, newValue);
  355.  
  356.             showURLStatus = flag;
  357.  
  358.             changes.firePropertyChange("showURLStatus", oldValue, newValue);
  359.         }
  360.     }
  361.  
  362.     /**
  363.      * If true show the linkURL in the status area when the mouse is over the button.
  364.      * If the linkURL is null, nothing is displayed, regardless of this flag.
  365.      * This flag also controls erasing of the status area after the URL has been displayed.
  366.      * @return true if the linkURL will be displayed in the status area when the mouse
  367.      * is over the button.
  368.      * @see #setShowURLStatus
  369.      */
  370.     public boolean isShowURLStatus()
  371.     {
  372.         return showURLStatus;
  373.     }
  374.  
  375.     /**
  376.      * Sets the current border color.
  377.      * @param color the new border color
  378.      * @exception PropertyVetoException
  379.      * if the specified property value is unacceptable
  380.      * @see #getBorderColor
  381.      */
  382.     public void setBorderColor(Color color) throws PropertyVetoException
  383.     {
  384.         if (!GeneralUtils.objectsEqual(borderColor, color))
  385.         {
  386.             Color oldValue = borderColor;
  387.  
  388.             vetos.fireVetoableChange("borderColor", oldValue, color);
  389.  
  390.             borderColor = color;
  391.             try
  392.             {
  393.                 disabledBorderColor    = ColorUtils.lighten(borderColor,    0.466);
  394.             }
  395.             catch (IllegalArgumentException exc) {}
  396.             repaint();
  397.  
  398.             changes.firePropertyChange("borderColor", oldValue, color);
  399.         }
  400.     }
  401.  
  402.     /**
  403.      * Gets the current border color.
  404.      * @return the current border color
  405.      * @see #setBorderColor
  406.      */
  407.     public Color getBorderColor()
  408.     {
  409.         return borderColor;
  410.     }
  411.  
  412.     /**
  413.      * Sets the current button color.
  414.      * @param color the new button color.  The highlights of the button are
  415.      * derived from this color.
  416.      * @exception PropertyVetoException
  417.      * if the specified property value is unacceptable
  418.      * @see #getButtonColor
  419.      */
  420.     public void setButtonColor(Color color) throws PropertyVetoException
  421.     {
  422.         if (!GeneralUtils.objectsEqual(buttonColor, color))
  423.         {
  424.             Color oldValue = buttonColor;
  425.  
  426.             vetos.fireVetoableChange("buttonColor", oldValue, color);
  427.             buttonColor = color;
  428.             try
  429.             {
  430.                 hilightColor            = ColorUtils.lighten(buttonColor,    0.600);
  431.                 pressedHilightColor        = ColorUtils.darken(buttonColor,    0.580);
  432.                 disabledHilightColor    = ColorUtils.lighten(buttonColor,    0.666);
  433.                 shadowColor                = ColorUtils.darken(buttonColor,    0.250);
  434.                 pressedShadowColor        = ColorUtils.darken(buttonColor,    0.100);
  435.                 disabledShadowColor        = ColorUtils.darken(buttonColor,    0.166);
  436.                 disabledButtonColor        = ColorUtils.lighten(buttonColor,    0.333);
  437.                 pressedButtonColor        = ColorUtils.darken(buttonColor,    0.250);
  438.             }
  439.             catch (IllegalArgumentException exc) {}
  440.             repaint();
  441.  
  442.             changes.firePropertyChange("buttonColor", oldValue, color);
  443.         }
  444.     }
  445.  
  446.     /**
  447.      * Gets the current button color.
  448.      * @return the current button color
  449.      * @see #setButtonColor
  450.      */
  451.     public Color getButtonColor()
  452.     {
  453.         return buttonColor;
  454.     }
  455.  
  456.     /**
  457.      * Sets the URL of the document to link to when the button is clicked.
  458.      * @param url the URL
  459.      * @exception java.beans.PropertyVetoException
  460.      * if the specified property value is unacceptable
  461.      * @see #getLinkURL
  462.      */
  463.     public void setLinkURL(URL url) throws PropertyVetoException
  464.     {
  465.         if(!GeneralUtils.objectsEqual(linkURL, url))
  466.         {
  467.             URL oldValue = linkURL;
  468.  
  469.             vetos.fireVetoableChange("linkURL", oldValue, url);
  470.             linkURL = url;
  471.             changes.firePropertyChange("linkURL", oldValue, url);
  472.         }
  473.     }
  474.  
  475.     /**
  476.      * Returns the URL of the document to link to when the button is clicked.
  477.      * @see #setLinkURL
  478.      */
  479.     public URL getLinkURL()
  480.     {
  481.         return linkURL;
  482.     }
  483.  
  484.     /**
  485.      * Sets the frame specifier for showing a URL document in a browser or applet
  486.      * viewer. It is interpreted as follows:
  487.      * <UL>
  488.      * <DT>"_self"  show document in the current frame</DT>
  489.      * <DT>"_parent"    show document in the parent frame</DT>
  490.      * <DT>"_top"   show document in the topmost frame</DT>
  491.      * <DT>"_blank" show document in a new unnamed toplevel window</DT>
  492.      * <DT>all others   show document in a new toplevel window with the given name</DT>
  493.      * </UL>
  494.      * @param newFrame the frame specifier
  495.      * @exception java.beans.PropertyVetoException
  496.      * if the specified property value is unacceptable
  497.      * @see #getFrame
  498.      * @see symantec.itools.util.GeneralUtils#frameTarget_self
  499.      * @see symantec.itools.util.GeneralUtils#frameTarget_parent
  500.      * @see symantec.itools.util.GeneralUtils#frameTarget_top
  501.      * @see symantec.itools.util.GeneralUtils#frameTarget_blank
  502.      */
  503.     public void setFrame(String newFrame) throws PropertyVetoException
  504.     {
  505.         String oldValue = frame;
  506.  
  507.         vetos.fireVetoableChange("frame", oldValue, newFrame);
  508.  
  509.         frame = newFrame;
  510.  
  511.         changes.firePropertyChange("frame", oldValue, newFrame);
  512.     }
  513.  
  514.     /**
  515.      * Gets the frame specifier for showing a URL document in a browser or applet
  516.      * viewer. It is interpreted as follows:
  517.      * <UL>
  518.      * <DT>"_self"  show document in the current frame</DT>
  519.      * <DT>"_parent"    show document in the parent frame</DT>
  520.      * <DT>"_top"   show document in the topmost frame</DT>
  521.      * <DT>"_blank" show document in a new unnamed toplevel window</DT>
  522.      * <DT>all others   show document in a new toplevel window with the given name</DT>
  523.      * </UL>
  524.      * @return the frame specifier
  525.      * @see #setFrame
  526.      * @see symantec.itools.util.GeneralUtils#frameTarget_self
  527.      * @see symantec.itools.util.GeneralUtils#frameTarget_parent
  528.      * @see symantec.itools.util.GeneralUtils#frameTarget_top
  529.      * @see symantec.itools.util.GeneralUtils#frameTarget_blank
  530.      */
  531.     public String getFrame()
  532.     {
  533.         return frame;
  534.     }
  535.  
  536.     /**
  537.      * Ensures that this component is laid out properly, as needed.
  538.      * This is a standard Java AWT method which gets called by the AWT to
  539.      * make sure this component and its subcomponents have a valid layout.
  540.      * If this component was made invalid with a call to invalidate(), then
  541.      * it is laid out again.
  542.      *
  543.      * It is overridden here to locate the applet containing this component.
  544.      *
  545.      * @see java.awt.Component#invalidate
  546.      */
  547.     public void validate()
  548.     {
  549.         // On validation, try to find the containing applet.  If we can find
  550.         // it, we don't bother doing the link...
  551.         if (context == null)
  552.         {
  553.             Container c;
  554.  
  555.             c = getParent();
  556.  
  557.             while (c != null)
  558.             {
  559.                 if (c instanceof Applet)
  560.                 {
  561.                     setAppletContext(((Applet) c).getAppletContext());
  562.                     break;
  563.                 }
  564.  
  565.                 c = c.getParent();
  566.             }
  567.         }
  568.     }
  569.  
  570.     /**
  571.      * Enables this component so that it will respond to user input.
  572.      * This is a standard Java AWT method which gets called to enable or disable
  573.      * this component. Once enabled this component will respond to user input.
  574.      *
  575.      * @param flag true if the component is to be enabled; false if it is to be disabled.
  576.      * @see java.awt.Component#isEnabled
  577.      */
  578.     public void setEnabled(boolean flag)
  579.     {
  580.         if(isEnabled() != flag)
  581.         {
  582.             if(flag)
  583.             {
  584.                 // !!! LAB !!!    This MUST be a call to super.enable(), not super.enable(boolean)
  585.                 //                or super.setEnabled(boolean)  If it is not, then it will result
  586.                 //                in an endless loop!
  587.                 super.enable();
  588.                 pressed = false;
  589.                 pressedAdjustment = 0;
  590.             }
  591.             else
  592.             {
  593.                 // !!! LAB !!!    This MUST be a call to super.disable(), not super.enable(boolean)
  594.                 //                or super.setEnabled(boolean)  If it is not, then it will result
  595.                 //                in an endless loop!
  596.                 super.disable();
  597.                 if (notifyTimer != null)
  598.                 {
  599.                     notifyTimer.stop();
  600.                 }
  601.  
  602.                 pressed = false;
  603.                 pressedAdjustment = 0;
  604.             }
  605.  
  606.             repaint();
  607.         }
  608.     }
  609.  
  610.     /**
  611.      * @deprecated
  612.      * @see #setEnabled
  613.      */
  614.     public void enable()
  615.     {
  616.         setEnabled(true);
  617.     }
  618.  
  619.     /**
  620.      * @deprecated
  621.      * @see #setEnabled
  622.      */
  623.     public void disable()
  624.     {
  625.         setEnabled(false);
  626.     }
  627.  
  628.     /**
  629.      * Tells this component that it has been added to a container.
  630.      * This is a standard Java AWT method which gets called by the AWT when
  631.      * this component is added to a container. Typically, it is used to
  632.      * create this component's peer.
  633.      *
  634.      * It has been overridden here to hook-up event listeners.
  635.      *
  636.      * @see #removeNotify
  637.      */
  638.     public synchronized void addNotify()
  639.     {
  640.         errors = ResourceBundle.getBundle("symantec.itools.resources.ErrorsBundle");
  641.  
  642.         //Hook up listeners
  643.         if (focus == null)
  644.         {
  645.             focus = new Focus();
  646.             addFocusListener(focus);
  647.         }
  648.         if (key == null)
  649.         {
  650.             key = new Key();
  651.             addKeyListener(key);
  652.         }
  653.         if (mouse == null)
  654.         {
  655.             mouse = new Mouse();
  656.             addMouseListener(mouse);
  657.         }
  658.         if (bevelVeto == null)
  659.         {
  660.             bevelVeto = new BevelVeto();
  661.             addBevelHeightListener(bevelVeto);
  662.         }
  663.         if (frameVeto == null)
  664.         {
  665.             frameVeto = new FrameVeto();
  666.             addFrameListener(frameVeto);
  667.         }
  668.         //Add after the listeners are hooked up
  669.         super.addNotify();
  670.  
  671.         isAdded = true;
  672.         verifyContstrainedPropertyValues();
  673.  
  674.         // On addNotify, try to find the containing applet.
  675.         if (context == null)
  676.         {
  677.             Container c;
  678.  
  679.             c = getParent();
  680.  
  681.             while (c != null)
  682.             {
  683.                 if (c instanceof Applet)
  684.                 {
  685.                     setAppletContext(((Applet) c).getAppletContext());
  686.                     break;
  687.                 }
  688.  
  689.                 c = c.getParent();
  690.             }
  691.         }
  692.     }
  693.  
  694.     /**
  695.      * Tells this component that it is being removed from a container.
  696.      * This is a standard Java AWT method which gets called by the AWT when
  697.      * this component is removed from a container. Typically, it is used to
  698.      * destroy the peers of this component and all its subcomponents.
  699.      *
  700.      * It has been overridden here to unhook event listeners.
  701.      *
  702.      * @see #addNotify
  703.      */
  704.     public synchronized void removeNotify()
  705.     {
  706.         //Unhook listeners
  707.         if (focus != null)
  708.         {
  709.             removeFocusListener(focus);
  710.             focus = null;
  711.         }
  712.         if (key != null)
  713.         {
  714.             removeKeyListener(key);
  715.             key = null;
  716.         }
  717.         if (mouse != null)
  718.         {
  719.             removeMouseListener(mouse);
  720.             mouse = null;
  721.         }
  722.         if (bevelVeto != null)
  723.         {
  724.             removeBevelHeightListener(bevelVeto);
  725.             bevelVeto = null;
  726.         }
  727.         if (frameVeto != null)
  728.         {
  729.             removeFrameListener(frameVeto);
  730.             frameVeto = null;
  731.         }
  732.  
  733.         super.removeNotify();
  734.         isAdded = false;
  735.     }
  736.  
  737.     /**
  738.      * Handles redrawing of this component on the screen.
  739.      * This is a standard Java AWT method which gets called by the Java
  740.      * AWT (repaint()) to handle repainting this component on the screen.
  741.      * The graphics context clipping region is set to the bounding rectangle
  742.      * of this component and its [0,0] coordinate is this component's
  743.      * top-left corner.
  744.      * Typically this method paints the background color to clear the
  745.      * component's drawing space, sets graphics context to be the foreground
  746.      * color, and then calls paint() to draw the component.
  747.      *
  748.      * It is overridden here to prevent the flicker associated with the standard
  749.      * update() method's repainting of the background before painting the component
  750.      * itself.
  751.      *
  752.      * @param g the graphics context
  753.      * @see java.awt.Component#repaint
  754.      * @see #paint
  755.      */
  756.     public void update(Graphics g)
  757.     {
  758.         paint(g);
  759.     }
  760.  
  761.     /**
  762.      * Paints this component using the given graphics context.
  763.      * This is a standard Java AWT method which typically gets called
  764.      * by the AWT to handle painting this component. It paints this component
  765.      * using the given graphics context. The graphics context clipping region
  766.      * is set to the bounding rectangle of this component and its [0,0]
  767.      * coordinate is this component's top-left corner.
  768.      *
  769.      * @param g the graphics context used for painting
  770.      * @see java.awt.Component#repaint
  771.      * @see #update
  772.      */
  773.     public void paint(Graphics g)
  774.     {
  775.         Dimension size = getSize();
  776.         //Work arround for potential problem on Unix where paint gets called with
  777.         //zero width and height.  -LAB
  778.         if (size.width > 0 && size.height > 0)
  779.         {
  780.             updateButtonImage();
  781.             g.drawImage(buttonImage, 0, 0, this);
  782.         }
  783.     }
  784.  
  785.     /**
  786.      * Returns the recommended dimensions to properly display this component.
  787.      * This is a standard Java AWT method which gets called to determine
  788.      * the recommended size of this component.
  789.      */
  790.     public Dimension getPreferredSize()
  791.     {
  792.         return new Dimension(bevel + bevel + 2, bevel + bevel + 2);
  793.     }
  794.  
  795.     /**
  796.      * @deprecated
  797.      * @see #getPreferredSize
  798.      */
  799.     public Dimension preferredSize()
  800.     {
  801.         return getPreferredSize();
  802.     }
  803.  
  804.     /**
  805.      * Returns the minimum dimensions to properly display this component.
  806.      * This is a standard Java AWT method which gets called to determine
  807.      * the minimum size of this component.
  808.      * It simply returns the results of a call to preferedSize().
  809.      */
  810.     public Dimension getMinimumSize()
  811.     {
  812.         return getPreferredSize();
  813.     }
  814.  
  815.     /**
  816.      * @deprecated
  817.      * @see #getMinimumSize
  818.      */
  819.     public Dimension minimumSize()
  820.     {
  821.         return getMinimumSize();
  822.     }
  823.  
  824.     public boolean isFocusTraversable()
  825.     {
  826.         return true;
  827.     }
  828.  
  829.     /**
  830.      * Makes the button act as if it was pressed, drawing
  831.      * as if it were clicked and sending an action event as if it
  832.      * were clicked.
  833.      */
  834.     public void simulateClick()
  835.     {
  836.         //pressed
  837.         requestFocus();
  838.         inButton    = true;
  839.         pressed        = true;
  840.         released    = false;
  841.         if(useOffset)
  842.             pressedAdjustment = bevel;
  843.         paint(getGraphics());
  844.  
  845.         //Wait for a bit
  846.         try { Thread.sleep(120); } catch (java.lang.InterruptedException exc) {}
  847.  
  848.         //released
  849.         inButton    = false;
  850.         pressed = false;
  851.         pressedAdjustment = 0;
  852.         linkToURL();
  853.         sourceActionEvent();
  854.         released = true;
  855.         repaint();
  856.     }
  857.  
  858.     /**
  859.      * Adds a listener for all event changes.
  860.      * @param listener the listener to add.
  861.      * @see #removePropertyChangeListener
  862.      */
  863.     public synchronized void addPropertyChangeListener(PropertyChangeListener listener)
  864.     {
  865.         changes.addPropertyChangeListener(listener);
  866.     }
  867.  
  868.     /**
  869.      * Removes a listener for all event changes.
  870.      * @param listener the listener to remove.
  871.      * @see #addPropertyChangeListener
  872.      */
  873.     public synchronized void removePropertyChangeListener(PropertyChangeListener listener)
  874.     {
  875.         changes.removePropertyChangeListener(listener);
  876.     }
  877.  
  878.     /**
  879.      * Adds a vetoable listener for all event changes.
  880.      * @param listener the listener to add.
  881.      * @see #removeVetoableChangeListener
  882.      */
  883.     public synchronized void addVetoableChangeListener(VetoableChangeListener listener)
  884.     {
  885.         vetos.addVetoableChangeListener(listener);
  886.     }
  887.  
  888.     /**
  889.      * Removes a vetoable listener for all event changes.
  890.      * @param listener the listener to remove.
  891.      * @see #addVetoableChangeListener
  892.      */
  893.     public synchronized void removeVetoableChangeListener(VetoableChangeListener listener)
  894.     {
  895.         vetos.removeVetoableChangeListener(listener);
  896.     }
  897.  
  898.     /**
  899.      * Adds a listener for the BevelHeight property changes.
  900.      * @param listener the listener to add.
  901.      * @see #removeBevelHeightListener(java.beans.PropertyChangeListener)
  902.      */
  903.     public synchronized void addBevelHeightListener(PropertyChangeListener listener)
  904.     {
  905.         changes.addPropertyChangeListener("bevelHeight", listener);
  906.     }
  907.  
  908.     /**
  909.      * Removes a listener for the BevelHeight property changes.
  910.      * @param listener the listener to remove.
  911.      * @see #addBevelHeightListener(java.beans.PropertyChangeListener)
  912.      */
  913.     public synchronized void removeBevelHeightListener(PropertyChangeListener listener)
  914.     {
  915.         changes.removePropertyChangeListener("bevelHeight", listener);
  916.     }
  917.  
  918.     /**
  919.      * Adds a vetoable listener for the BevelHeight property changes.
  920.      * @param listener the listener to add.
  921.      * @see #removeBevelHeightListener(java.beans.VetoableChangeListener)
  922.      */
  923.     public synchronized void addBevelHeightListener(VetoableChangeListener listener)
  924.     {
  925.         vetos.addVetoableChangeListener("bevelHeight", listener);
  926.     }
  927.  
  928.     /**
  929.      * Removes a vetoable listener for the BevelHeight property changes.
  930.      * @param listener the listener to remove.
  931.      * @see #addBevelHeightListener(java.beans.VetoableChangeListener)
  932.      */
  933.     public synchronized void removeBevelHeightListener(VetoableChangeListener listener)
  934.     {
  935.         vetos.removeVetoableChangeListener("bevelHeight", listener);
  936.     }
  937.  
  938.     /**
  939.      * Adds a listener for the Frame property changes.
  940.      * @param listener the listener to add.
  941.      * @see #removeFrameListener(java.beans.PropertyChangeListener)
  942.      */
  943.     public synchronized void addFrameListener(PropertyChangeListener listener)
  944.     {
  945.         changes.addPropertyChangeListener("frame", listener);
  946.     }
  947.  
  948.     /**
  949.      * Removes a listener for the Frame property changes.
  950.      * @param listener the listener to remove.
  951.      * @see #addFrameListener(java.beans.PropertyChangeListener)
  952.      */
  953.     public synchronized void removeFrameListener(PropertyChangeListener listener)
  954.     {
  955.         changes.removePropertyChangeListener("frame", listener);
  956.     }
  957.  
  958.     /**
  959.      * Adds a vetoable listener for the Frame property changes.
  960.      * @param listener the listener to add.
  961.      * @see #removeFrameListener(java.beans.VetoableChangeListener)
  962.      */
  963.     public synchronized void addFrameListener(VetoableChangeListener listener)
  964.     {
  965.         vetos.addVetoableChangeListener("frame", listener);
  966.     }
  967.  
  968.     /**
  969.      * Removes a vetoable listener for the Frame property changes.
  970.      * @param listener the listener to remove.
  971.      * @see #addFrameListener(java.beans.VetoableChangeListener)
  972.      */
  973.     public synchronized void removeFrameListener(VetoableChangeListener listener)
  974.     {
  975.         vetos.removeVetoableChangeListener("frame", listener);
  976.     }
  977.  
  978.     /**
  979.      * Sets the command name of the action event fired by this button.
  980.      * @param command The name of the action event command fired by this button
  981.      * @exception PropertyVetoException
  982.      * if the specified property value is unacceptable
  983.      */
  984.     public void setActionCommand(String command) throws PropertyVetoException
  985.     {
  986.         String oldValue = actionCommand;
  987.  
  988.         vetos.fireVetoableChange("actionCommand", oldValue, command);
  989.         actionCommand = command;
  990.         changes.firePropertyChange("actionCommand", oldValue, command);
  991.     }
  992.  
  993.     /**
  994.      * Returns the command name of the action event fired by this button.
  995.      * @return the action command name
  996.      */
  997.     public String getActionCommand()
  998.     {
  999.         return actionCommand;
  1000.     }
  1001.  
  1002.     /**
  1003.      * Adds the specified action listener to receive action events
  1004.      * from this button.
  1005.      * @param l the action listener
  1006.      */
  1007.     public synchronized void addActionListener(ActionListener l)
  1008.     {
  1009.         actionListener = AWTEventMulticaster.add(actionListener, l);
  1010.     }
  1011.  
  1012.     /**
  1013.      * Removes the specified action listener so it no longer receives
  1014.      * action events from this button.
  1015.      * @param l the action listener
  1016.      */
  1017.     public synchronized void removeActionListener(ActionListener l)
  1018.     {
  1019.         actionListener = AWTEventMulticaster.remove(actionListener, l);
  1020.     }
  1021.  
  1022.     class Focus extends java.awt.event.FocusAdapter implements java.io.Serializable
  1023.     {
  1024.         public void focusGained(FocusEvent e)
  1025.         {
  1026.             hasFocus = true;
  1027.             repaint();
  1028.         }
  1029.  
  1030.         public void focusLost(FocusEvent e)
  1031.         {
  1032.             hasFocus = false;
  1033.             repaint();
  1034.         }
  1035.     }
  1036.  
  1037.     class Key extends java.awt.event.KeyAdapter implements java.io.Serializable
  1038.     {
  1039.         public void keyPressed(KeyEvent evt)
  1040.         {
  1041.             //boolean isSpaceBar = (evt.getKeyCode() & KeyEvent.VK_SPACE) == KeyEvent.VK_SPACE;
  1042.             boolean isSpaceBar = (evt.getKeyCode() == KeyEvent.VK_SPACE);
  1043.  
  1044.             if(isSpaceBar && hasFocus && showFocus && !symantec.itools.lang.OS.isMacintosh()) {
  1045.             inButton = true;
  1046.             notified = false;
  1047.             if (notifyTimer != null && notifyWhilePressed && !running)
  1048.             {
  1049.                 running     = true;
  1050.                 notifyTimer.start();
  1051.             }
  1052.  
  1053.             pressed           = true;
  1054.             released          = false;
  1055.             if(useOffset)
  1056.                 pressedAdjustment = bevel;
  1057.             repaint();
  1058.             }
  1059.  
  1060.         }
  1061.         public void keyReleased(KeyEvent evt)
  1062.         {
  1063.             //boolean isSpaceBar = (evt.getKeyCode() & KeyEvent.VK_SPACE) == KeyEvent.VK_SPACE;
  1064.             boolean isSpaceBar = (evt.getKeyCode() == KeyEvent.VK_SPACE);
  1065.  
  1066.             if(isSpaceBar && hasFocus && showFocus && !symantec.itools.lang.OS.isMacintosh()) {
  1067.             inButton = false;
  1068.             if (notifyTimer != null && running)
  1069.             {
  1070.                 running = false;
  1071.                 notifyTimer.stop();
  1072.             }
  1073.  
  1074.             if (pressed)
  1075.             {
  1076.                 pressed = false;
  1077.                 pressedAdjustment = 0;
  1078.  
  1079.                 if (!notifyWhilePressed || !notified)
  1080.                 {
  1081.                     //Handle going to the linkURL
  1082.                     linkToURL();
  1083.                     sourceActionEvent();
  1084.                 }
  1085.             }
  1086.  
  1087.             released = true;
  1088.             repaint();
  1089.             }
  1090.  
  1091.         }
  1092.     }
  1093.  
  1094.     /**
  1095.      * This is the Mouse Event handling innerclass.
  1096.      */
  1097.     class Mouse extends java.awt.event.MouseAdapter implements java.io.Serializable
  1098.     {
  1099.         /**
  1100.          * Handles the Mouse Pressed events
  1101.          * If the notifyWhilePressed flag is true the notification Timer is started
  1102.          * @param e the MouseEvent
  1103.          * @see #setNotifyWhilePressed
  1104.          * @see #setNotifyDelay
  1105.          * @see #mouseReleased
  1106.          */
  1107.         public void mousePressed(MouseEvent e)
  1108.         {
  1109.             requestFocus();
  1110.             notified = false;
  1111.             if (notifyTimer != null && notifyWhilePressed && !running)
  1112.             {
  1113.                 running     = true;
  1114.                 notifyTimer.start();
  1115.             }
  1116.  
  1117.             pressed           = true;
  1118.             released          = false;
  1119.             if(useOffset)
  1120.                 pressedAdjustment = bevel;
  1121.             repaint();
  1122.         }
  1123.  
  1124.         /**
  1125.          * Handles the Mouse Released events
  1126.          * If the notification timer is running it is stopped.
  1127.          * If the mouse was pressed inside the button then fire an action event.
  1128.          * @param e the MouseEvent
  1129.          * @see #mousePressed
  1130.          */
  1131.         public void mouseReleased(MouseEvent e)
  1132.         {
  1133.             if (notifyTimer != null && running)
  1134.             {
  1135.                 running = false;
  1136.                 notifyTimer.stop();
  1137.             }
  1138.  
  1139.             if (pressed)
  1140.             {
  1141.                 pressed = false;
  1142.                 pressedAdjustment = 0;
  1143.  
  1144.                 if (!notifyWhilePressed || !notified)
  1145.                 {
  1146.                     //Handle going to the linkURL
  1147.                     linkToURL();
  1148.                     sourceActionEvent();
  1149.                 }
  1150.             }
  1151.  
  1152.             released = true;
  1153.             if(inButton)
  1154.                 repaint();
  1155.         }
  1156.  
  1157.         /**
  1158.          * Handles Mouse Entered events
  1159.          * @param e the MouseEvent
  1160.          */
  1161.         public void mouseEntered(MouseEvent e)
  1162.         {
  1163.             inButton = true;
  1164.  
  1165.             //Display the linkURL
  1166.             if (showURLStatus && context != null && linkURL != null)
  1167.             {
  1168.                 context.showStatus(linkURL.toString());
  1169.             }
  1170.  
  1171.             if (!released)
  1172.             {
  1173.                 pressed = true;
  1174.                 if(useOffset)
  1175.                     pressedAdjustment = bevel;
  1176.  
  1177.                 if(notifyTimer != null && notifyWhilePressed && !running)
  1178.                 {
  1179.                     running = true;
  1180.                     notifyTimer.start();
  1181.                 }
  1182.                 repaint();
  1183.             }
  1184.         }
  1185.  
  1186.         /**
  1187.          * Handles Mouse Exited events
  1188.          * @param e the MouseEvent
  1189.          */
  1190.         public void mouseExited(MouseEvent e)
  1191.         {
  1192.             inButton = false;
  1193.  
  1194.             if (notifyTimer != null && running)
  1195.             {
  1196.                 running = false;
  1197.                 notifyTimer.stop();
  1198.             }
  1199.  
  1200.             if (pressed)
  1201.             {
  1202.                 pressed = false;
  1203.                 pressedAdjustment = 0;
  1204.                 repaint();
  1205.             }
  1206.  
  1207.             if (showURLStatus && context != null && linkURL != null)
  1208.             {
  1209.                 context.showStatus("");
  1210.             }
  1211.         }
  1212.     }
  1213.  
  1214.     /**
  1215.      * This is the Action Event handling innerclass.
  1216.      */
  1217.     class Action implements java.awt.event.ActionListener, java.io.Serializable
  1218.     {
  1219.         //Implement ActionListener to catch ActionEvents sent by either the notifyTimer.
  1220.         /**
  1221.          * Handles Action events
  1222.          * @param e the ActionEvent
  1223.          */
  1224.         public void actionPerformed(ActionEvent e)
  1225.         {
  1226.             if (e.getSource() == notifyTimer && notifyWhilePressed && !java.beans.Beans.isDesignTime())
  1227.             {
  1228.                 notified = true;
  1229.                 sourceActionEvent();
  1230.                 return;
  1231.             }
  1232.         }
  1233.     }
  1234.  
  1235.     /**
  1236.      * This is the PropertyChangeEvent handling inner class for the constrained BevelHeight property.
  1237.      * Handles vetoing BevelHeights that are not valid.
  1238.      */
  1239.     class BevelVeto implements java.beans.VetoableChangeListener, java.io.Serializable
  1240.     {
  1241.         /**
  1242.          * This method gets called when an attempt to change the constrained BevelHeight property is made.
  1243.          * Ensures the given bevel size is valid for this button.
  1244.          *
  1245.          * @param     e a <code>PropertyChangeEvent</code> object describing the
  1246.          *             event source and the property that has changed.
  1247.          * @exception PropertyVetoException if the recipient wishes the property
  1248.          *              change to be rolled back.
  1249.          */
  1250.         public void vetoableChange(PropertyChangeEvent e) throws PropertyVetoException
  1251.         {
  1252.             int i = ((Integer)e.getNewValue()).intValue();
  1253.             if (!isValidBevelSize(i))
  1254.             {
  1255.                 throw new PropertyVetoException(errors.getString("InvalidBevelSize") + i, e);
  1256.             }
  1257.         }
  1258.     }
  1259.  
  1260.     /**
  1261.      * This is the PropertyChangeEvent handling inner class for the constrained Frame property.
  1262.      * Handles vetoing Frame strings that are not valid.
  1263.      */
  1264.     class FrameVeto implements java.beans.VetoableChangeListener, java.io.Serializable
  1265.     {
  1266.         /**
  1267.          * This method gets called when an attempt to change the constrained Frame property is made.
  1268.          * Ensures the given Frame string is valid for this button.
  1269.          *
  1270.          * @param     e a <code>PropertyChangeEvent</code> object describing the
  1271.          *             event source and the property that has changed.
  1272.          * @exception PropertyVetoException if the recipient wishes the property
  1273.          *              change to be rolled back.
  1274.          */
  1275.         public void vetoableChange(PropertyChangeEvent e) throws PropertyVetoException
  1276.         {
  1277.             String string = (String)e.getNewValue();
  1278.             if (!isValidFrame(string))
  1279.             {
  1280.                 throw new PropertyVetoException(errors.getString("InvalidFrame") + string, e);
  1281.             }
  1282.         }
  1283.     }
  1284.  
  1285.     /**
  1286.      * Fire an action event to the listeners.
  1287.      */
  1288.     protected void sourceActionEvent()
  1289.     {
  1290.         if (actionListener != null)
  1291.             actionListener.actionPerformed(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, actionCommand));
  1292.     }
  1293.  
  1294.     /**
  1295.      * Is the given bevel size valid for this button.
  1296.      * @param i the given bevel size
  1297.      * @return true if the given bevel size is acceptable, false if not.
  1298.      */
  1299.     protected boolean isValidBevelSize(int i)
  1300.     {
  1301.         Dimension s = getSize();
  1302.  
  1303.         if (i < 0 || i >= (s.width / 2) || i >= (s.height / 2))
  1304.             return false;
  1305.         else
  1306.             return true;
  1307.     }
  1308.  
  1309.     /**
  1310.      * Is the given frame string valid.
  1311.      * @param string the given frame
  1312.      * @return true if the given frame is acceptable, false if not.
  1313.      * To be valid it has to be null, or one of the four strings below:
  1314.      * @see symantec.itools.util.GeneralUtils#frameTarget_self
  1315.      * @see symantec.itools.util.GeneralUtils#frameTarget_parent
  1316.      * @see symantec.itools.util.GeneralUtils#frameTarget_top
  1317.      * @see symantec.itools.util.GeneralUtils#frameTarget_blank
  1318.      */
  1319.     protected boolean isValidFrame(String string)
  1320.     {
  1321.         if(string == null || string.equals(""))
  1322.             return true;
  1323.  
  1324.         if(    string.equals(GeneralUtils.frameTarget_self)    ||
  1325.             string.equals(GeneralUtils.frameTarget_parent)    ||
  1326.             string.equals(GeneralUtils.frameTarget_top)        ||
  1327.             string.equals(GeneralUtils.frameTarget_blank)    )
  1328.             return true;
  1329.         else
  1330.             return false;
  1331.     }
  1332.  
  1333.     /**
  1334.      * Tell the browser to show the document referenced by the linkURL.
  1335.      * If the frame specifier is not null or empty, then tell the browser
  1336.      * to open the document with that frame.
  1337.      */
  1338.     protected void linkToURL()
  1339.     {
  1340.         if (context != null && linkURL != null)
  1341.         {
  1342.             if (frame == null || frame.length() == 0)
  1343.                 context.showDocument(linkURL);
  1344.             else
  1345.                 context.showDocument(linkURL, frame);
  1346.         }
  1347.     }
  1348.  
  1349.     /**
  1350.      * Called after addNotify to set the internally constrined properties to their
  1351.      * temporary values to validate them now that the component has been added to the form.
  1352.      * This is used to avoid code-gen order dependencies, since VC generates all property
  1353.      * manipulating code before adding the component to its container.
  1354.      * Subclasses should override this function for any internally constrained properties,
  1355.      * and call the super version in the overridden version.
  1356.      */
  1357.     protected void verifyContstrainedPropertyValues()
  1358.     {
  1359.         try { setBevelHeight(tempBevelHeight); } catch (PropertyVetoException exc) { /*Silently verify.*/ }
  1360.     }
  1361.  
  1362.     /**
  1363.      * Sets the applet context used to view documents.
  1364.      * @param c the new applet context
  1365.      */
  1366.     protected void setAppletContext(AppletContext c)
  1367.     {
  1368.         context = c;
  1369.     }
  1370.  
  1371.     /**
  1372.      * Maintains the buttonImage size and draws the
  1373.      * button in the buttonImage offscreen image.
  1374.      * @see #paint
  1375.      */
  1376.     protected void updateButtonImage()
  1377.     {
  1378.         Dimension s    = getSize();
  1379.         int width    = s.width;
  1380.         int height    = s.height;
  1381.         int x        = bevel  + 1;
  1382.         int y        = bevel  + 1;
  1383.         int w        = width  - 1;
  1384.         int h        = height - 1;
  1385.         int i;
  1386.         Color highlight1, highlight2, fillColor, tempBorderColor;
  1387.         boolean raised = !(pressed && inButton);
  1388.  
  1389.         if(isButtonImageInvalid())
  1390.         {
  1391.             buttonImage = createImage(width, height);
  1392.             try
  1393.             {
  1394.                 MediaTracker tracker = new MediaTracker(this);
  1395.                 tracker.addImage(buttonImage, 0);
  1396.                 tracker.waitForID(0);
  1397.             }
  1398.             catch(InterruptedException e){}
  1399.         }
  1400.  
  1401.         buttonImageGraphics = buttonImage.getGraphics();
  1402.         if ( buttonImageGraphics.getClip() == null )
  1403.             buttonImageGraphics.clipRect( 0, 0, width, height );
  1404.         Color oldColor = buttonImageGraphics.getColor();
  1405.  
  1406.         if(isEnabled())    //Enabled
  1407.         {
  1408.             tempBorderColor = borderColor;
  1409.  
  1410.             if (raised)
  1411.             {
  1412.                 fillColor    = buttonColor;
  1413.                 highlight1    = hilightColor;
  1414.                 highlight2    = shadowColor;
  1415.  
  1416.             }
  1417.             else    //Pressed
  1418.             {
  1419.                 fillColor    = pressedButtonColor;
  1420.                 highlight1    = pressedHilightColor;
  1421.                 highlight2    = pressedShadowColor;
  1422.  
  1423.             }
  1424.         }
  1425.         else //Disabled
  1426.         {
  1427.             tempBorderColor    = disabledBorderColor;
  1428.             fillColor        = disabledButtonColor;
  1429.             highlight1        = disabledHilightColor;
  1430.             highlight2        = disabledShadowColor;
  1431.         }
  1432.  
  1433.         if(!raised && useOffset)
  1434.         {
  1435.             //Fill the button content
  1436.             buttonImageGraphics.setColor(fillColor);
  1437.             buttonImageGraphics.fillRect(x, y, w - x, h - y);
  1438.  
  1439.             //Draw the bevels
  1440.             buttonImageGraphics.setColor(highlight1);
  1441.             for(i = 1; i <= bevel; i++)
  1442.             {
  1443.                 buttonImageGraphics.drawLine(i, i, i, h);
  1444.                 buttonImageGraphics.drawLine(i, i, w, i);
  1445.             }
  1446.         }
  1447.  
  1448.         if(raised || !useOffset)
  1449.         {
  1450.             //Fill the button content
  1451.             buttonImageGraphics.setColor(fillColor);
  1452.             buttonImageGraphics.fillRect(x, y, w - x, h - y);
  1453.  
  1454.             //Draw the bevels
  1455.             buttonImageGraphics.setColor(highlight1);
  1456.             for(i = 1; i <= bevel; i++)
  1457.             {
  1458.                 buttonImageGraphics.drawLine(i, i, i, h - i);
  1459.                 buttonImageGraphics.drawLine(i, i, w - i, i);
  1460.             }
  1461.             buttonImageGraphics.setColor(highlight2);
  1462.             for(i = 1; i <= bevel; ++i)
  1463.             {
  1464.                 buttonImageGraphics.drawLine(i, h - i, w - i, h - i);
  1465.                 buttonImageGraphics.drawLine(w - i, i, w - i, h - i);
  1466.             }
  1467.         }
  1468.  
  1469.         //Draw the border
  1470.         buttonImageGraphics.setColor(tempBorderColor);
  1471.         buttonImageGraphics.drawLine(1, 0, w - 1, 0);
  1472.         buttonImageGraphics.drawLine(0, 1, 0, h - 1);
  1473.         buttonImageGraphics.drawLine(1, h, w - 1, h);
  1474.         buttonImageGraphics.drawLine(w, h - 1, w, 1);
  1475.  
  1476.         if (hasFocus && showFocus) {
  1477.             buttonImageGraphics.setColor(java.awt.Color.darkGray);
  1478.             for(x = 3; x <= w - 3; x += 3)
  1479.                 buttonImageGraphics.drawLine(x, 3, x+1, 3);
  1480.             for(y = 3; y <= h - 3; y += 3)
  1481.                 buttonImageGraphics.drawLine(3, y, 3, y+1);
  1482.             for(x = 3; x <= w - 3; x += 3)
  1483.                 buttonImageGraphics.drawLine(x, h-3, x+1, h-3);
  1484.             for(y = 3; y <= h - 3; y += 3)
  1485.                 buttonImageGraphics.drawLine(w-3, y, w-3, y+1);
  1486.         }
  1487.  
  1488.  
  1489.         //!!! LAB !!! This should be changed to setClip when it works.
  1490.         //Set the clipping area to be the inside of the button.
  1491.         buttonImageGraphics.clipRect(bevel + 1, bevel + 1, width - bevel - bevel - 2, height - bevel - bevel - 2);
  1492.  
  1493.         //Restore the original color
  1494.         buttonImageGraphics.setColor(oldColor);
  1495.     }
  1496.  
  1497.     /**
  1498.      * Returns true if a button image has been set, but it is not the
  1499.      * size of this component.
  1500.      */
  1501.     protected boolean isButtonImageInvalid()
  1502.     {
  1503.         Dimension s = getSize();
  1504.         return (buttonImage == null || s.width     != buttonImage.getWidth(this) || s.height != buttonImage.getHeight(this));
  1505.     }
  1506.  
  1507.     /**
  1508.      * True if the button is currently pressed.
  1509.      */
  1510.     transient protected boolean   pressed;
  1511.     /**
  1512.      * True if the button has been released.
  1513.      */
  1514.     transient protected boolean   released;
  1515.     /**
  1516.      * True if the mouse is over this button.
  1517.      */
  1518.     transient protected boolean   inButton;
  1519.     /**
  1520.      * If true the button will continuously post events while pressed.
  1521.      */
  1522.     protected boolean   notifyWhilePressed;
  1523.     /**
  1524.      * True if the notify timer is running.
  1525.      */
  1526.     transient protected boolean   running;
  1527.     /**
  1528.      * True if a notification has been posted in response to a mouse down.
  1529.      */
  1530.     transient protected boolean   notified;
  1531.     /**
  1532.      * If <code>true</code> this component will visually indicate when it has the focus.
  1533.      * This is done by drawing a focus rectangle within the component as needed.
  1534.      */
  1535.     protected boolean   showFocus = false;
  1536.     /**
  1537.      * If true set pressedAdjustment accordingly, else, it is always 0.
  1538.      */
  1539.     protected boolean   useOffset;
  1540.     /**
  1541.      * If true show the linkURL in the status area when the mouse is over the button.
  1542.      * If the linkURL is null, nothing is displayed, regardless of this flag.
  1543.      * This flag also controls erasing of the status area after the URL has been displayed.
  1544.      */
  1545.     protected boolean   showURLStatus;
  1546.     /**
  1547.      * Keeps track of wheather or not the button is added to a container.
  1548.      * Check before attempting to getFontMetrics() to avoid getting a null pointer.
  1549.      */
  1550.     transient protected boolean   isAdded;
  1551.     /**
  1552.      * The "height" (cross-section) of a beveled edge, in pixels.
  1553.      */
  1554.     protected int bevel;
  1555.     /**
  1556.      * Internal use.
  1557.      * Bevel height value stored until this component is added to a container.
  1558.      * It is then used to set the real bevel height value.
  1559.      * This avoids code-gen order dependencies.
  1560.      */
  1561.     protected int tempBevelHeight;
  1562.     /**
  1563.      * The delay in milliseconds between notifications while the button is pressed.
  1564.      */
  1565.     protected int       notifyDelay;
  1566.     /**
  1567.      * A drawing location adjustment for the 3-D bevel while button is pressed.
  1568.      */
  1569.     protected int       pressedAdjustment;
  1570.     /**
  1571.      * Frame specifier for showing a URL document in a browser or applet
  1572.      * viewer. It is interpreted as follows:
  1573.      * <UL>
  1574.      * <DT>"_self"  show document in the current frame</DT>
  1575.      * <DT>"_parent"    show document in the parent frame</DT>
  1576.      * <DT>"_top"   show document in the topmost frame</DT>
  1577.      * <DT>"_blank" show document in a new unnamed toplevel window</DT>
  1578.      * <DT>all others   show document in a new toplevel window with the given name</DT>
  1579.      * </UL>
  1580.      */
  1581.     protected String    frame = null;
  1582.     /**
  1583.      * The color of the border around the button.
  1584.      */
  1585.     protected Color    borderColor;
  1586.     /**
  1587.      * The color of the content of the button.  The highlights are derived from this color.
  1588.      */
  1589.     protected Color    buttonColor;
  1590.     /**
  1591.      * Timer used to time notification events while button pressed.
  1592.      */
  1593.     protected Timer    notifyTimer;
  1594.     /**
  1595.      *    The offscreen buffer to draw the button in.
  1596.      */
  1597.     transient protected Image    buttonImage = null;
  1598.     /**
  1599.      *    The Graphics of the offscreen buffer to draw the button in.
  1600.      */
  1601.     transient protected Graphics    buttonImageGraphics = null;
  1602.     /**
  1603.      * The URL of the document to show when the button is clicked.
  1604.      */
  1605.     protected URL    linkURL = null;
  1606.     /**
  1607.      * Applet context that shows the document.
  1608.      */
  1609.     transient protected AppletContext context = null;
  1610.     /**
  1611.      * Error strings.
  1612.      */
  1613.     transient protected ResourceBundle errors;
  1614.  
  1615.     String actionCommand;
  1616.     ActionListener actionListener = null;
  1617.     transient boolean hasFocus = false;
  1618.  
  1619.     private Color hilightColor            = null;
  1620.     private Color pressedHilightColor    = null;
  1621.     private Color disabledHilightColor    = null;
  1622.     private Color shadowColor            = null;
  1623.     private Color pressedShadowColor    = null;
  1624.     private Color disabledShadowColor    = null;
  1625.     private Color disabledBorderColor    = null;
  1626.     private Color disabledButtonColor    = null;
  1627.     private Color pressedButtonColor    = null;
  1628.     private Key key = null;
  1629.     private Focus focus = null;
  1630.     private Action    action        = new Action();
  1631.     private Mouse        mouse        = null;
  1632.     private BevelVeto    bevelVeto    = null;
  1633.     private FrameVeto    frameVeto    = null;
  1634.     private symantec.itools.beans.VetoableChangeSupport vetos = new symantec.itools.beans.VetoableChangeSupport(this);
  1635.     private symantec.itools.beans.PropertyChangeSupport changes = new symantec.itools.beans.PropertyChangeSupport(this);
  1636. }
  1637.